/**
 * 上海中赢金融信息服务有限公司
 * Copyright (c) 2016-2026 hmc,Inc.All Rights Reserved.
 */
package com.sys.midware.rdb.datasource;

import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;
import com.sys.midware.logger.Logger;
import com.sys.midware.logger.LoggerFactory;
import com.sys.midware.rdb.config.RDBConfig;
import com.sys.midware.rdb.config.RDBPoolConfig;
import com.sys.midware.rdb.exception.RDBException;

/**
 * ocean工具类
 * 
 * @author mobing@b5m.com
 * @see com.b5m.BDataSourceUtil.dal.datasource.BOceanDataSourceUtil.ocean.core.OceanUtils
 * @version V0.0.1-SNAPSHOT, 2015-08-13上午9:47:27
 * @description
 * 
 */
public class BDataSourceUtil {

    private final static Logger LOG = LoggerFactory.getLogger(BDataSourceUtil.class);

    private final static int RETRY_TIMES = 2;

    /**
     * 获取当前有效连接
     * 
     * @param node
     * @return
     */
    public static Connection getValidConnection(DataSource ds) {
        if (ds == null) {
            throw new NullPointerException("DataSourceNode");
        }
        LOG.info("获取有效连接...");
        Connection conn = null;
        // DataSource ds = node.getNodeDataSource();
        for (int i = 0; i < RETRY_TIMES; ++i) {
            try {
                conn = ds.getConnection();
                if (conn == null || conn.isClosed()) {
                    continue;
                }
                return conn;
            } catch (Exception e) {
                LOG.error("获取有效连接异常" + e.getMessage(), e);
                continue;
            }
        }
        throw new RDBException("Get connection failure");
    }

    /**
     * 设置当前有效数据源
     * 
     * @param dataSourceKey
     *            数据源KEY
     * @return
     */
    public static boolean setValidDataSource(String dataSourceKey) {
        LOG.info("设置当前有效数据源, 根据参数Key=" + dataSourceKey);
        Map<String, DataSource> nodeMap = DataSourceMapHolder.get();
        DataSource currentDSnode = nodeMap.get(dataSourceKey);
        if (currentDSnode == null) {
            throw new NullPointerException("DataSourceNode");
        } else {
            DataSourceHolder.put(currentDSnode);
            return true;
        }
    }

    // 设置map类型datasource
    public static void setNodeDataSourceMap(Map<String, RDBConfig> rdbConfigMap) {
        RDBConfig rdbConfig = null;
        Map<String, DataSource> dataSourcesNodeMap = new HashMap<String, DataSource>();
        // 如果没有传nodename，则随机取一个RDB配置
        for (Entry<String, RDBConfig> map : rdbConfigMap.entrySet()) {
            rdbConfig = map.getValue();
            dataSourcesNodeMap.put(map.getKey(), initDataSource(rdbConfig));
            if (rdbConfig == null) {
                continue;
            }
        }

        DataSourceMapHolder.put(dataSourcesNodeMap);

    }

    /**
     * 初始化datasource
     * 
     * @param nodeCfg
     * @return
     */
    public static DataSource initDataSource(RDBConfig RDBConfig) {
        try {
            DruidDataSource ds = new DruidDataSource();
            RDBPoolConfig poolConfig = RDBConfig.getRDBPoolConfig();

            ds.setUrl(poolConfig.getUrl());
            ds.setUsername(poolConfig.getUsername());
            ds.setPassword(poolConfig.getPassword());
            ds.setDriverClassName(poolConfig.getDriverClassName());
            ds.setInitialSize(poolConfig.getInitialSize());
            ds.setMaxActive(poolConfig.getMaxActive());
            ds.setMinIdle(poolConfig.getMinIdle());
            ds.setMaxWait(poolConfig.getMaxWait());

            if (poolConfig.getLogAbandoned() != null) {
                ds.setLogAbandoned(poolConfig.getLogAbandoned());
            }
            if (poolConfig.getRemoveAbandoned() != null) {
                ds.setRemoveAbandoned(poolConfig.getRemoveAbandoned());
            }
            if (poolConfig.getRemoveAbandonedTimeout() != null) {
                ds.setRemoveAbandonedTimeout(poolConfig.getRemoveAbandonedTimeout());
            }
            if (poolConfig.getTimeBetweenEvictionRunsMillis() != null) {
                ds.setTimeBetweenEvictionRunsMillis(poolConfig.getTimeBetweenEvictionRunsMillis());
            }
            if (poolConfig.getMinEvictableIdleTimeMillis() != null) {
                ds.setMinEvictableIdleTimeMillis(poolConfig.getMinEvictableIdleTimeMillis());
            }
            if (poolConfig.getValidationQuery() != null) {
                ds.setValidationQuery(poolConfig.getValidationQuery());
            }
            if (poolConfig.getTestOnBorrow() != null) {
                ds.setTestOnBorrow(poolConfig.getTestOnBorrow());
            }
            if (poolConfig.getTestOnReturn() != null) {
                ds.setTestOnReturn(poolConfig.getTestOnReturn());
            }
            if (poolConfig.getTestWhileIdle() != null) {
                ds.setTestWhileIdle(poolConfig.getTestWhileIdle());
            }
            if (poolConfig.getPoolPreparedStatements() != null) {
                ds.setPoolPreparedStatements(poolConfig.getPoolPreparedStatements());
            }
            if (poolConfig.getMaxPoolPreparedStatementPerConnectionSize() != null) {
                ds.setMaxPoolPreparedStatementPerConnectionSize(
                        poolConfig.getMaxPoolPreparedStatementPerConnectionSize());
            }
            if (poolConfig.getFilters() != null) {
                ds.setFilters(poolConfig.getFilters());
            }
            ds.init();
            return ds;
        } catch (Exception e) {
            throw new RDBException(e);
        }
    }

}